#include <iostream>
#include "main_bak.h"

using namespace std;

const char* VERTEX_SHADER = "#version 330 core\n"
                            "in vec4 a_position;\n"
                            "void main(){\n"
                            "    gl_Position = a_position;\n"
                            "    gl_PointSize = 10.0f;\n"
                            "}";
const char* FRAGMENT_SHADER = "#version 330 core\n"
                              "out vec4 FragColor;\n"
                              "void main(){\n"
                              "    FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
                              "}";
static int WINDOW_WIDTH = 400;
static int WINDOW_HEIGHT = 400;

int main1() {
    //1、初始化GLFW
    if (!glfwInit()) {
        cout << "glfw init is failed!" << endl;
        return -1;
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//opengl3.3
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //2.创建一个窗口
    GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT,"OpenGL3",NULL,NULL);
    if (nullptr == window) {
        cout << "create window is failed!" << endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    //2.1将指针交给GLAD管理
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        cout << "glad load glfw pointer failed!" << endl;
        return -1;
    }

    //2.2初始化视口和绑定窗口大小发生改变时监听
    framebuff_size_callback(window,WINDOW_WIDTH,WINDOW_HEIGHT);
    glfwSetFramebufferSizeCallback(window, framebuff_size_callback);

    int program = getProgram(window, VERTEX_SHADER, FRAGMENT_SHADER);
    if(-1 == program){
        return program;
    }

    float vertexs[] = {
        // v0-v1-v2-v3 front
        0.5, 0.5, 0.5,//0
        -0.5,0.5,0.5,//1
        -0.5,-0.5,0.5,//2
        0.5,0.5,0.5,//0
        -0.5,-0.5,0.5,//2
        0.5,-0.5,0.5,//3

        // v0-v3-v4-v5 right
        0.5, 0.5, 0.5,//0
        0.5,-0.5,0.5,//3
        0.5, -0.5, -0.5,//4
        0.5, 0.5, 0.5,//0
        0.5,-0.5,-0.5,//4
        0.5,0.5,-0.5,//5

        // v0-v5-v6-v1 up
        0.5, 0.5, 0.5,//0
        0.5,0.5,-0.5,//5
        -0.5,0.5,-0.5,//6
        0.5, 0.5, 0.5,//0
        -0.5,0.5,-0.5,//6
        -0.5,0.5,0.5,//1

        // v1-v6-v7-v2 left
        -0.5, 0.5, 0.5,//1
        -0.5, 0.5, -0.5,//6
        -0.5,-0.5, -0.5,//7
        -0.5, 0.5, 0.5,//1
        -0.5,-0.5, -0.5,//7
        -0.5,-0.5,0.5,//2

        // v7-v4-v3-v2 bottom
        -0.5,-0.5,-0.5,//7
        0.5,-0.5,-0.5,//4
        0.5,-0.5,0.5,//3
        -0.5,-0.5,-0.5,//7
        0.5,-0.5,0.5,//3
        -0.5,-0.5,0.5,//2

        // v4-v7-v6-v5 back
        0.5,-0.5,-0.5,//4
        -0.5,-0.5,-0.5,//7
        -0.5, 0.5, -0.5,//6
        0.5,-0.5,-0.5,//4
        -0.5, 0.5, -0.5,//6
        0.5,0.5,-0.5,//5
    };

    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    unsigned int VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);


    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    //3.主循环
    while (!glfwWindowShouldClose(window))
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(program);

        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

        glDrawArrays(GL_TRIANGLES, 0 , 16*6);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    //4.关闭
    glfwTerminate();
    return 0;
}

void framebuff_size_callback(GLFWwindow *pWwindow, const int width, const int height) {
    glViewport(0, 0, width, height);
}


unsigned int getProgram(GLFWwindow *pWwindow, const char* vertexShaderSource, const char* fragmentShaderSource) {
    //标识编译和链接是否成功
    int logLength = 512;
    int success;
    char infoLog[logLength];
    unsigned  int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VERTEX_SHADER, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(!success){
        glGetShaderInfoLog(vertexShader, logLength, NULL, infoLog);
        cout << "vertexShader-compile failed." << infoLog << endl;
        return  -1;
    }

    unsigned  int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &FRAGMENT_SHADER, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success){
        glGetShaderInfoLog(fragmentShader, logLength, NULL, infoLog);
        cout << "fragmentShader-compile failed." << infoLog << endl;
        return  -1;
    }

    unsigned int program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if(!success){
        glGetProgramInfoLog(program, logLength, NULL, infoLog);
        cout << "fragmentShader-compile failed." << infoLog << endl;
        return  -1;
    }

    glDetachShader(program, vertexShader);
    glDetachShader(program, fragmentShader);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return program;
}
